package com.xique.door.service.impl;

import com.github.pagehelper.PageInfo;
import com.xique.common.core.utils.OrikaUtil;
import com.xique.common.core.utils.SecurityUtils;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.common.core.web.page.TableDataInfo;
import com.xique.door.bean.domain.*;
import com.xique.door.bean.request.card.DeviceAddCardRequest;
import com.xique.door.bean.request.card.DeviceCardListRequest;
import com.xique.door.bean.request.card.DeviceCardSelectListRequest;
import com.xique.door.bean.request.device.DeviceDeleteRequest;
import com.xique.door.bean.search.AreaBuildingHouseSearch;
import com.xique.door.bean.vo.area.AreaBuildingHouseVo;
import com.xique.door.bean.vo.card.CardUserVo;
import com.xique.door.command.ICardCommandBizService;
import com.xique.door.device.freeview.constant.CommandStatus;
import com.xique.door.mapper.CardAuthorizationMapper;
import com.xique.door.mapper.DCardMapper;
import com.xique.door.service.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.spi.LocaleNameProvider;
import java.util.stream.Collectors;

@Service
public class CardAuthorizationServiceImpl implements ICardAuthorizationService {

    @Autowired
    private DCardMapper dCardMapper;

    @Autowired
    private IDCardDeviceService cardDeviceService;

    @Autowired
    private ICardCommandBizService cardCommandBizService;

    @Autowired
    private IAccessDeviceService accessDeviceService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IDCardHouseService cardHouseService;

    @Autowired
    private IDCardService dCardService;

    @Autowired
    private CardAuthorizationMapper cardAuthorizationMapper;

    @Autowired
    private IBuildHouseService buildHouseService;

    /**
     * 设备已授权的卡号
     */
    public TableDataInfo selectAssignedDeviceCardList(DeviceCardSelectListRequest request) {

        DCard dCard = OrikaUtil.convert(request, DCard.class);

        if (request.getUserName() != null && !"".equals(request.getUserName())) {
            UserV1 userV1 = new UserV1();
            userV1.setUserName(request.getUserName());
            UserV1 userV2 = userService.selectUserV1(userV1);
            if (userV2 != null) {
                dCard.setUserId(userV2.getId());
            }
        }
        List<DCard> cards = cardAuthorizationMapper.selectDCardList(dCard, request);
        List<CardUserVo> cardUserVos = OrikaUtil.converts(cards, CardUserVo.class);
        List<Long> cardIds = cards.stream().map(DCard::getId).collect(Collectors.toList());
        List<CardDevice> cardDevices = new ArrayList<>();
        List<AreaBuildingHouseVo> areaInfos = new ArrayList<>();

        if (!cardIds.isEmpty()) {
            String houseIdStr = cards.stream().map(DCard::getHouseIds).collect(Collectors.joining(","));
            List<String> houseIds = Arrays.asList(houseIdStr.split(","));
            areaInfos =
                    buildHouseService.selecAreaBuildingHouseInfoByCondition(
                            new AreaBuildingHouseSearch(houseIds));
            cardDevices = cardDeviceService.selectDCardDeviceList(new CardDevice(cardIds));
        }

        for (CardUserVo cardUserVo : cardUserVos) {
            Long userId = cardUserVo.getUserId();
            User user = userService.selectUserById(userId);
            if (user != null) {
                cardUserVo.setPhone(user.getPhone() != null ? user.getPhone() : null);
                cardUserVo.setUserName(user.getUserName());
            }

            List<AreaBuildingHouseVo> cardAreaInfos = new ArrayList<>();
            // 根据卡片绑定的房屋id查询房屋信息
            if (StringUtils.isNotEmpty(cardUserVo.getHouseIds())) {
                List<String> cardHosueIds = Arrays.asList(StringUtils.split(cardUserVo.getHouseIds(), ","));
                for (String cardHosueId : cardHosueIds) {
                    AreaBuildingHouseVo cardAreaInfo =
                            areaInfos.stream()
                                    .filter(e -> cardHosueId.equals(e.getHouseId()))
                                    .findAny()
                                    .orElse(null);
                    cardAreaInfos.add(cardAreaInfo);
                }
            }

            cardUserVo.setAreaInfos(cardAreaInfos);
            List<CardDevice> cardDevice =
                    cardDevices.stream()
                            .filter(
                                    e ->
                                            e.getCardId().equals(cardUserVo.getId())
                                                    && !CommandStatus.SUCCESS.equals(e.getStatus()))
                            .collect(Collectors.toList());

            cardUserVo.setErrorStatus(cardDevice.isEmpty() ? "0" : "1");
        }
        TableDataInfo tableDataInfo =
                new TableDataInfo(cardUserVos, (int) new PageInfo(cards).getTotal());
        return tableDataInfo;
    }

    public List<DCard> selectDCardDeviceList(Long parkId, Long deviceId) {
        DCard dCard = new DCard();
        dCard.setParkId(parkId);
        DeviceCardSelectListRequest request = new DeviceCardSelectListRequest();
        request.setDeviceId(deviceId);
        return cardAuthorizationMapper.selectDCardList(dCard, request);
    }

    /**
     * 设备未授权的卡号
     */
    public TableDataInfo selectUnAssignedDeviceCardList(
            DeviceCardSelectListRequest request, List<DCard> ids) {
        DCard dCard = OrikaUtil.convert(request, DCard.class);

        if (request.getUserName() != null && !"".equals(request.getUserName())) {
            UserV1 userV1 = new UserV1();
            userV1.setUserName(request.getUserName());
            userV1.setParkId(request.getParkId());
            UserV1 userV2 = userService.selectUserV1(userV1);
            if (userV2 != null) {
                dCard.setUserId(userV2.getId());
            }
        }

        List<DCard> cards = cardAuthorizationMapper.deviceCardUnAssigned(dCard, ids, request);
        List<CardUserVo> cardUserVos = OrikaUtil.converts(cards, CardUserVo.class);
        List<Long> cardIds = cards.stream().map(DCard::getId).collect(Collectors.toList());
        List<CardDevice> cardDevices = new ArrayList<>();
        List<AreaBuildingHouseVo> areaInfos = new ArrayList<>();

        if (!cardIds.isEmpty()) {
            String houseIdStr = cards.stream().map(DCard::getHouseIds).collect(Collectors.joining(","));
            List<String> houseIds = Arrays.asList(houseIdStr.split(","));
            areaInfos =
                    buildHouseService.selecAreaBuildingHouseInfoByCondition(
                            new AreaBuildingHouseSearch(houseIds));
            cardDevices = cardDeviceService.selectDCardDeviceList(new CardDevice(cardIds));
        }

        for (CardUserVo cardUserVo : cardUserVos) {
            Long userId = cardUserVo.getUserId();
            User user = userService.selectUserById(userId);
            if (user != null) {
                cardUserVo.setPhone(user.getPhone() != null ? user.getPhone() : null);
                cardUserVo.setUserName(user.getUserName());
            }
            List<AreaBuildingHouseVo> cardAreaInfos = new ArrayList<>();
            // 根据卡片绑定的房屋id查询房屋信息
            if (StringUtils.isNotEmpty(cardUserVo.getHouseIds())) {
                List<String> cardHosueIds = Arrays.asList(StringUtils.split(cardUserVo.getHouseIds(), ","));
                for (String cardHosueId : cardHosueIds) {
                    AreaBuildingHouseVo cardAreaInfo =
                            areaInfos.stream()
                                    .filter(e -> cardHosueId.equals(e.getHouseId()))
                                    .findAny()
                                    .orElse(null);
                    cardAreaInfos.add(cardAreaInfo);
                }
            }

            cardUserVo.setAreaInfos(cardAreaInfos);
            List<CardDevice> cardDevice =
                    cardDevices.stream()
                            .filter(
                                    e ->
                                            e.getCardId().equals(cardUserVo.getId())
                                                    && !CommandStatus.SUCCESS.equals(e.getStatus()))
                            .collect(Collectors.toList());

            cardUserVo.setErrorStatus(cardDevice.isEmpty() ? "0" : "1");
        }
        TableDataInfo tableDataInfo =
                new TableDataInfo(cardUserVos, (int) new PageInfo(cards).getTotal());
        return tableDataInfo;
    }

    /**
     * 卡片重新下发
     */
    @Override
    public AjaxResult addDeviceCard(DeviceAddCardRequest request) {
        AccessDevice accessDevice = accessDeviceService.selectAccessDeviceById(request.getDeviceId());
        StringBuilder stringBuilder = new StringBuilder("下发成功，等待设备处理。");
        List<DCard> cardList = new ArrayList<>();
        DCard card = dCardMapper.selectDCardById(request.getCardId());
        cardList.add(card);

        CardDevice search = new CardDevice();
        search.setCardId(card.getId());
        search.setDeviceId(request.getDeviceId());
        List<CardDevice> listCardDevice = cardDeviceService.selectDCardDeviceList(search);
        if (listCardDevice.isEmpty()) {
            return AjaxResult.success("");
        }

        for (CardDevice cardDevice : listCardDevice) {
            cardDevice.setUpdateTime(new Date());
            cardDevice.setUpdateBy(String.valueOf(SecurityUtils.getUserId()));
            cardDevice.setStatus(CommandStatus.SEND);
        }
        cardDeviceService.batchUpdateCardDevice(listCardDevice);

        cardCommandBizService.downCards(Collections.singletonList(accessDevice), cardList);
        return AjaxResult.success(stringBuilder.toString());
    }

    /**
     * 卡片解绑
     */
    @Override
    public AjaxResult deleteDeviceCard(DeviceAddCardRequest request) {

        DCard card = dCardMapper.selectDCardById(request.getCardId());
        CardDevice cardDevice = cardDeviceService.selectDCardDeviceById(request.getDeviceCardId());
        /** 调用设备删除卡片信息 */
        AjaxResult result =
                cardCommandBizService.deleteCard(card, Collections.singletonList(cardDevice));
        System.out.println(result.get("code"));
        if (result.get("code").equals(200)) {
            /** 删除卡片与设备的中间表 */
            cardDeviceService.deleteDCardDeviceById(request.getDeviceCardId());
            /** 删除卡片与房屋的中间表 */
            cardHouseService.deleteDCardHouseById(request.getHouseCardId());
        }
        return AjaxResult.success("解绑成功");
    }

    /**
     * 批量绑卡
     */
    public AjaxResult addDeviceCardList(DeviceCardListRequest request) {
        StringBuilder stringBuilder = new StringBuilder("下发成功，等待设备处理。");
        AccessDevice accessDevice = accessDeviceService.selectAccessDeviceById(request.getDeviceId());
        List<DCard> cardList = new ArrayList<>();
        List<CardDevice> cardDevices = new ArrayList<>();
        for (DeviceAddCardRequest card1 : request.getList()) {
            DCard card = dCardMapper.selectDCardById(card1.getCardId());
            cardList.add(card);
            User user = userService.selectUserById(card1.getUserId());
            CardDevice cardDevice = new CardDevice();
            cardDevice.setDeviceId(accessDevice.getId());
            cardDevice.setParkId(card.getParkId());
            cardDevice.setCustomId(card.getCustomId());
            cardDevice.setCardSn(card.getCardSn());
            cardDevice.setModel(accessDevice.getModel());
            cardDevice.setStatus(CommandStatus.SEND);
            cardDevice.setDevSn(accessDevice.getDevSn());
            cardDevice.setCardId(card.getId());
            cardDevice.setCreateBy(String.valueOf(SecurityUtils.getUserId()));
            cardDevice.setUpdateBy(cardDevice.getCreateBy());
            if (user != null) {
                card.setUserName(user.getUserName());
                card.setPersonType(user.getPersonType());
            }
            cardDevices.add(cardDevice);
        }
        cardDeviceService.batchInsertCardDevices(cardDevices);
        cardCommandBizService.downCards(Collections.singletonList(accessDevice), cardList);

        return AjaxResult.success(stringBuilder.toString());
    }

    /**
     * 卡片批量重新下发
     */
    @Override
    public AjaxResult addDeviceCardLists(DeviceCardListRequest request) {

        AccessDevice accessDevice = accessDeviceService.selectAccessDeviceById(request.getDeviceId());
        StringBuilder stringBuilder = new StringBuilder("下发成功，等待设备处理。");
        List<DCard> cardList = new ArrayList<>();
        if (request.getList().size() > 0) {
            for (DeviceAddCardRequest req : request.getList()) {
                DCard card = dCardMapper.selectDCardById(req.getCardId());
                cardList.add(card);

                CardDevice search = new CardDevice();
                search.setCardId(card.getId());
                search.setDeviceId(request.getDeviceId());
                List<CardDevice> listCardDevice = cardDeviceService.selectDCardDeviceList(search);
                if (listCardDevice.isEmpty()) {
                    return AjaxResult.success("");
                }

                for (CardDevice cardDevice : listCardDevice) {
                    cardDevice.setUpdateTime(new Date());
                    cardDevice.setUpdateBy(String.valueOf(SecurityUtils.getUserId()));
                    cardDevice.setStatus(CommandStatus.SEND);
                }
                cardDeviceService.batchUpdateCardDevice(listCardDevice);
            }
            cardCommandBizService.downCards(Collections.singletonList(accessDevice), cardList);
        }
        return AjaxResult.success(stringBuilder.toString());
    }

    /**
     * @param request
     * @description: 全量下发设备中已有的卡片
     * @author taojc
     * @date: 2022/8/9 08:57
     */
    @Override
    public AjaxResult addAllDeviceCardLists(DeviceCardListRequest request) {
        AccessDevice accessDevice = accessDeviceService.selectAccessDeviceById(request.getDeviceId());
        CardDevice cardDeviceSearch = new CardDevice();
        cardDeviceSearch.setDeviceId(request.getDeviceId());
        List<CardDevice> cardDevices = cardDeviceService.selectDCardDeviceList(cardDeviceSearch);
        List<Long> cardIds = cardDevices.stream().map(CardDevice::getCardId).collect(Collectors.toList());
        List<DCard> dCards = dCardService.selectCardByIds(cardIds);
        // 过滤出需要下发的卡片
        List<DCard> needCommandCards = dCards.stream().filter(e -> StringUtils.isNotEmpty(e.getCardSn())).collect(Collectors.toList());
        for (CardDevice cardDevice : cardDevices) {
            DCard dCard = dCards.stream().filter(e -> e.getId().equals(cardDevice.getCardId())).findAny().orElse(null);
            cardDevice.setUpdateTime(new Date());
            if (StringUtils.isEmpty(accessDevice.getOnlineStatus()) || "offline".equals(accessDevice.getOnlineStatus())) {
                cardDevice.setStatus(CommandStatus.PENDING);
            } else {
                if (dCard != null && StringUtils.isNotEmpty(dCard.getCardSn())) {
                    cardDevice.setStatus(CommandStatus.SEND);
                } else {
                    cardDevice.setStatus(CommandStatus.NOFACE);
                }
            }
        }
        int i = cardDeviceService.batchUpdateCardDevice(cardDevices);
        if (!CollectionUtils.isEmpty(needCommandCards)) {
            cardCommandBizService.downCards(Collections.singletonList(accessDevice), needCommandCards);
        }
        return i > 0 ? AjaxResult.success("指令已发出，请等待设备处理后刷新页面") : AjaxResult.error();
    }

    /**
     * 卡片批量解绑
     */
    @Override
    public AjaxResult deleteDeviceCardList(DeviceCardListRequest request) {
        if (request.getList().size() > 0) {
            for (DeviceAddCardRequest req : request.getList()) {
                DCard card = dCardMapper.selectDCardById(req.getCardId());
                CardDevice cardDevice = cardDeviceService.selectDCardDeviceById(req.getDeviceCardId());
                /** 调用设备删除卡片信息 */
                AjaxResult result =
                        cardCommandBizService.deleteCard(card, Collections.singletonList(cardDevice));
                System.out.println(result.get("code"));
                if (result.get("code").equals(200)) {
                    /** 删除卡片与设备的中间表 */
                    cardDeviceService.deleteDCardDeviceById(req.getDeviceCardId());
                    /** 删除卡片与房屋的中间表 */
                    cardHouseService.deleteDCardHouseById(req.getHouseCardId());
                }
            }
            return AjaxResult.success("解绑成功");
        }
        return null;
    }

    /**
     * @param request
     * @description: 卡片全量解绑
     * @author taojc
     * @date: 2022/8/16
     */
    @Override
    public void deleteAllDeviceCardList(DeviceDeleteRequest request) {
        List<Integer> list =  cardAuthorizationMapper.selectDCardDeviceLists(SecurityUtils.getParkId(), request.getId());
        if(!CollectionUtils.isEmpty(list)){
            if(list.size()==1){
                cardAuthorizationMapper.deleteDCardAssignedId(list.get(0));
            }else{
                cardAuthorizationMapper.deleteDCardAssignedIds(list);
            }
        }
    }

    @Override
    public TableDataInfo selectDCardAdministration(DeviceCardSelectListRequest request) {
        DCard dCard = OrikaUtil.convert(request, DCard.class);
        if (request.getUserName() != null && !"".equals(request.getUserName())) {
            UserV1 userV1 = new UserV1();
            userV1.setUserName(request.getUserName());
            UserV1 userV2 = userService.selectUserV1(userV1);
            if (userV2 != null) {
                dCard.setUserId(userV2.getId());
            }
        }
        List<DCard> cards = cardAuthorizationMapper.selectDCardAdministration(dCard, request);
        List<CardUserVo> cardUserVos = OrikaUtil.converts(cards, CardUserVo.class);
        List<Long> cardIds = cards.stream().map(DCard::getId).collect(Collectors.toList());
        List<CardDevice> cardDevices = new ArrayList<>();
        List<AreaBuildingHouseVo> areaInfos = new ArrayList<>();
        ;
        if (!cardIds.isEmpty()) {
            String houseIdStr = cards.stream().map(DCard::getHouseIds).collect(Collectors.joining(","));
            List<String> houseIds = Arrays.asList(houseIdStr.split(","));
            areaInfos =
                    buildHouseService.selecAreaBuildingHouseInfoByCondition(
                            new AreaBuildingHouseSearch(houseIds));
            cardDevices = cardDeviceService.selectDCardDeviceList(new CardDevice(cardIds));
        }

        for (CardUserVo cardUserVo : cardUserVos) {
            Long userId = cardUserVo.getUserId();
            User user = userService.selectUserById(userId);
            if (user != null) {
                cardUserVo.setPhone(user.getPhone() != null ? user.getPhone() : null);
                cardUserVo.setUserName(user.getUserName());
            }
            List<AreaBuildingHouseVo> cardAreaInfos = new ArrayList<>();
            // 根据卡片绑定的房屋id查询房屋信息
            if (StringUtils.isNotEmpty(cardUserVo.getHouseIds())) {
                List<String> cardHosueIds = Arrays.asList(StringUtils.split(cardUserVo.getHouseIds(), ","));
                for (String cardHosueId : cardHosueIds) {
                    AreaBuildingHouseVo cardAreaInfo =
                            areaInfos.stream()
                                    .filter(e -> cardHosueId.equals(e.getHouseId()))
                                    .findAny()
                                    .orElse(null);
                    cardAreaInfos.add(cardAreaInfo);
                }
            }

            cardUserVo.setAreaInfos(cardAreaInfos);
            List<CardDevice> cardDevice =
                    cardDevices.stream()
                            .filter(
                                    e ->
                                            e.getCardId().equals(cardUserVo.getId())
                                                    && !CommandStatus.SUCCESS.equals(e.getStatus()))
                            .collect(Collectors.toList());

            cardUserVo.setErrorStatus(cardDevice.isEmpty() ? "0" : "1");
        }
        TableDataInfo tableDataInfo =
                new TableDataInfo(cardUserVos, (int) new PageInfo(cards).getTotal());
        return tableDataInfo;
    }
}
